`maximize-window.py` is a simple script that maximizes a GUI window.  It only works in X Window System.

Usage
-----
```
$ ./maximize-window.py WID
```
where `WID` is the window ID.  `WID` must be decimal.

Dependencies / Requirements
---------------------------
- X11
- an [EWMH-enabled](https://en.wikipedia.org/wiki/Extended_Window_Manager_Hints#List_of_window_managers_that_support_Extended_Window_Manager_Hints) window manager
- Python 3
- [xcffib package](https://github.com/tych0/xcffib) (which requires XCB)

Tested on Debian/MATE.  `python3-xcffib` version: 0.8.1-0.8.

Lack of robustness
------------------
The script aims to be simple.  It does not check commandline arguments.  Missing argument / invalid arguments trigger an exception.  Extra arguments are ignored.

Once in a while, `maximize-window.py` silently fails to maximize a window.  This is likely due to early disconnection though I'm not sure.  Try adding some delay before exiting script (see comment in source code).

Similar tools
-------------
Before we go on to explain `maximize-window.py`, you might wanna consider some other tools that may suit your needs better.

Some window managers provide built-in window management automation (e.g. [awesome](https://awesomewm.org/))

Standalone tools for X automation (including but not limited to):
  - [xdotool](https://github.com/jordansissel/xdotool/)
    - [python-xdo](https://gitlab.org/dkg/python-xdo)
  - GNU [Xnee](https://xnee.wordpress.com/)
  - [xautomation](https://hoopajoo.net/projects/xautomation.html)

Wayland automation:
  - [wtype](https://github.com/atx/wtype)

Faking keyboard and mouse input:
  - [ydotool](https://github.com/ReimuNotMoe/ydotool)
  - [libinputsynth](https://gitlab.freedesktop.org/xrdesktop/libinputsynth)
  - [python-evdev](https://github.com/gvalkov/python-evdev)
  - python-uinput
  - [python-keyboard](https://github.com/boppreh/keyboard)

You can also write your own program using EWMH, XTEST extension, or X Record extension.
- [XCB](https://xcb.freedesktop.org)
- [libXtst](git://anongit.freedesktop.org/git/xorg/lib/libXtst)
- [libXext](git://anongit.freedesktop.org/git/xorg/lib/libXext)
- Rust [x11](https://lib.rs/crates/x11)
- Rust [x11rb](https://lib.rs/crates/x11rb)

More explanations please?
-------------------------
#### What's X11?
A windowing system allows multiple apps to draw on one screen without messing each other up.
X is a windowing system protocol.  [X11](https://www.x.org/releases/current/doc/xproto/x11protocol.html) is the 11th version.  Look it up on Wikipedia.

#### How do I know if I'm using X11?
X11 is the de facto windowing system protocol on \*nix systems.  If you are using Linux in 2022, you are probably using X11.

X is old and encumbered.  A new project called Wayland is underway.  If you are reading this in the future, Wayland may have replaced X.

To find out, search for a process named `Xorg` in System Monitor.  Alternatively, if you prefer commandline:
```sh
$ pgrep --list-full Xorg
910 /usr/lib/xorg/Xorg :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
```

#### What's EWMH?
[Extended Window Manager Hints](https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html) is a specification that defines interactions between window managers and applications.

For maximum flexibility, X11 provide mechanism rather than policy.
For example, X11 provides a way for clients to send messages to each other but it does not specify what the messages contain or what to use them for.
EWMH is a protocol that builds on X11 and specifies some essential elements of modern desktop environments that X doesn't specify (like workspaces and maximized windows).

#### How do I know if my window manager supports EWMH?
All major desktop envionments support EWMH.  Check your WM's documentation / [Wikipedia](https://en.wikipedia.org/wiki/Extended_Window_Manager_Hints#List_of_window_managers_that_support_Extended_Window_Manager_Hints).

#### How do I obtain the window ID?
To select a window interactively, run `xwininfo`.  Look for a line that looks like
```txt
xwininfo: Window id: 0x880002c "Wikipedia, the free encyclopedia — Mozilla Firefox"
```
0x880002c is the window ID.  (Use `xwininfo -int` to convert it to decimal.)

If you want to use `maximize-window.py`, chances are you want to automate window maximization.  In that case, `xwininfo` is not very helpful.

There is no universal way to obtain window ID automatically.  Depending on your needs, here is an incomplete list of options:
  - the `WINDOWID` environment variable contains the window ID of (an ancestor of) your script
  - some programs provide a way to query their window ID
    - e.g. Vim (GTK flavor): `window_id="$(gvim --echo-wid | head -n1)"  &&  window_id="${window_id##*WID: }"`

As a last resort, consider listing all windows and querying each window's `_NET_WM_PID`.

If you end up querying `_NET_WM_PID`, it's probably a good idea to ditch `maximize-window.py` and write your own (non-shell) code
because doing this in shell is very slow (~ 1 sec).
To speed up querying `_NET_WM_PID` in shell, replace `bash`/`zsh` with `dash` and try to avoid forking too many processes (`sed`, `grep`, …).  Example:
```sh
local wid pid
xwininfo -root -tree | command grep Firefox | while read wid
do
	wid="${wid#*0x}"
	wid="0x${wid%% *}"

	pid="$(xprop -id "$wid" _NET_WM_PID)"
	pid="${pid#*= }"

	echo "WID = $wid  PID = $pid"
done
```

Todo
----
- See source code.
- Learn how to package Python code
  - Upload to PyPI

Contributing
------------
This README was written at late night; it probably contains a bunch of errors (or missing info).  I'd appreciate any corrections.

Any other contribution is welcomed too.

License
-------
Apache v2.0
